package com.hfjyz.judge.judgecall.service;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.transaction.annotation.Transactional;

import com.hfjyz.base.bean.SearchCondition;
import com.hfjyz.base.constant.BaseConstant;
import com.hfjyz.base.entity.CallEntity;
import com.hfjyz.base.entity.JudgeEntity;
import com.hfjyz.base.exception.BaseException;
import com.hfjyz.base.util.ExcelUtil;
import com.hfjyz.judge.judge.bean.JudgeBean;
import com.hfjyz.judge.judge.dao.JudgeDao;
import com.hfjyz.judge.judgecall.bean.JudgeCallBean;
import com.hfjyz.judge.judgecall.bean.JudgeCallExcelBean;
import com.hfjyz.judge.judgecall.bean.JudgeCallSearchBean;
import com.hfjyz.judge.judgecall.dao.JudgeCallDao;
import com.hfjyz.judge.judgecall.entity.JudgeCallEntity;

public class JudgeCallService {
    private static final Log SYS_LOG = LogFactory.getLog(BaseConstant.SYS_LOG);

    private JudgeCallDao dao = null;
    
    private JudgeDao judgeDao = null;

    public JudgeCallDao getDao() {
        return dao;
    }

    public void setDao(JudgeCallDao dao) {
        this.dao = dao;
    }

    public JudgeDao getJudgeDao() {
        return judgeDao;
    }

    public void setJudgeDao(JudgeDao judgeDao) {
        this.judgeDao = judgeDao;
    }

    public List<JudgeCallBean> findJudgeCall(SearchCondition cond,
            JudgeCallSearchBean judgeCallSearch) throws BaseException {
        try {
            List<JudgeCallEntity> entityList = null;
            if (judgeCallSearch != null) {
                entityList = dao.findCall(cond, judgeCallSearch.getWhereClause("call", "judge"),
                        judgeCallSearch.getParamList());
            } else {
                entityList = dao.findCall(cond, null, null);
            }

            List<JudgeCallBean> beanList = new ArrayList<JudgeCallBean>();
            for (JudgeCallEntity entity : entityList) {
                JudgeCallBean bean = new JudgeCallBean(entity);
                beanList.add(bean);
            }

            SYS_LOG.info("评委调用信息取得成功。");
            return beanList;
        } catch (Exception e) {
            SYS_LOG.error("评委调用信息取得失败！", e);
            throw new BaseException("评委调用信息取得失败！", e);
        }
    }

    public long getJudgeCallCount(JudgeCallSearchBean judgeCallSearch) throws BaseException {
        try {
            long count = 0L;
            if (judgeCallSearch != null) {
                count = dao.countCall(" JudgeEntity judge ", "judge",
                        judgeCallSearch.getWhereClause("call", "judge"),
                        judgeCallSearch.getParamList());
            } else {
                count = dao.countCall(" JudgeEntity judge ", "judge", null, null);
            }
            SYS_LOG.info("评委调用信息总数取得成功。 总数=" + count);

            return count;
        } catch (Exception e) {
            SYS_LOG.error("评委调用信息总数取得失败！", e);
            throw new BaseException("评委调用信息总数取得失败！", e);
        }
    }

    @Transactional
    public void saveJudgeCall(List<JudgeCallBean> beanList) throws BaseException {
        for (JudgeCallBean bean : beanList) {
            saveJudgeCall(bean);
        }
    }

    @Transactional
    public void saveJudgeCall(JudgeCallBean bean) throws BaseException {
        try {
            String msg = bean.validate();
            if (msg != null && !msg.isEmpty()) {
                throw new BaseException(msg);
            }
            CallEntity entity = null;
            boolean isAdd = false;
            if (bean.getId() != null) {
                entity = dao.get(bean.getId());
            } else {
                long count = dao.countCallByTargetAndName(bean.getCallName(), 
                        bean.getTarget().getId());
                if (count > 0) {
                    throw new BaseException("指定的专家调用信息已经存在，请确认！");
                }
                entity = new CallEntity();
                isAdd = true;
            }
            mergeEntity(bean, entity);

            dao.saveOrUpdate(entity);
            if (isAdd) {
                // 更新调用次数
                JudgeEntity judge = judgeDao.get(bean.getTarget().getId());
                judge.setCallTimes(judge.getCallTimes() + 1);
                judgeDao.saveOrUpdate(judge);
            }

            SYS_LOG.info("评委调用信息保存成功。 judgeCall=" + bean.toString());
        } catch (BaseException e) {
            SYS_LOG.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            SYS_LOG.error("评委调用信息保存失败！", e);
            throw new BaseException("评委调用信息保存失败！", e);
        }
    }

    private void mergeEntity(JudgeCallBean bean, CallEntity e) {
        e.setCallName(bean.getCallName());
        e.setCallReason(bean.getCallReason());
        e.setCallRemark(bean.getCallRemark());
        e.setCallType(dao.getType());
        e.setId(bean.getId());
        e.setTargetId(bean.getTarget().getId());
        e.setCallAim(bean.getCallAim());
    }

    @Transactional
    public void deleteJudgeCall(List<Integer> idList) throws BaseException {
        try {
            for (Integer id : idList) {
                CallEntity call = dao.get(id);
                JudgeEntity judge = judgeDao.get(call.getTargetId());
                judge.setCallTimes(judge.getCallTimes() - 1);

                dao.delete(id);
                judgeDao.saveOrUpdate(judge);
            }
            SYS_LOG.info("评委调用删除成功。 idList=" + idList.toString());
        } catch (Exception e) {
            SYS_LOG.error("评委调用删除失败！", e);
            throw new BaseException("评委调用删除失败！", e);
        }
    }

    public JudgeCallBean updateInitJudgeCall(Integer id) throws BaseException {
        try {
            CallEntity call = dao.get(id);
            JudgeEntity judge = dao.findTargetById(call.getTargetId());
            JudgeCallBean bean = new JudgeCallBean(call, judge);

            SYS_LOG.info("取得评委信息成功。 bean=" + bean);

            return bean;
        } catch (Exception e) {
            SYS_LOG.error("取得评委信息失败！", e);
            throw new BaseException("取得评委信息失败！", e);
        }
    }

    public Workbook exportJudgeCall(String templatePath, List<JudgeCallExcelBean> judgeCallList)
            throws BaseException {
        InputStream inputXLStream = null;
        try {
            inputXLStream = new BufferedInputStream(new FileInputStream(templatePath));
            ExcelUtil<JudgeCallExcelBean> util = new ExcelUtil<JudgeCallExcelBean>();
            
            return util.writeToExcel(inputXLStream, judgeCallList, BaseConstant.EXCEL_JUDGE_BEAN_LIST);
        } catch (Exception e) {
            throw new BaseException("导出Excel失败！", e);
        }
    }

    public List<JudgeBean> findAllJudge() throws BaseException {
        try {
            List<JudgeEntity> entityList = judgeDao.findAll();

            List<JudgeBean> beanList = new ArrayList<JudgeBean>();
            for (JudgeEntity entity : entityList) {
                JudgeBean bean = new JudgeBean(entity);
                beanList.add(bean);
            }

            SYS_LOG.info("取得所有评委信息成功。");
            return beanList;
        } catch (Exception e) {
            SYS_LOG.error("取得所有评委信息失败。", e);
            throw new BaseException("取得所有评委信息失败。", e);
        }
    }
}
